package tp.pr5.mv.window;

import java.util.Map;
import java.util.TreeMap;

import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;

import tp.pr5.mv.Memory;

@SuppressWarnings("serial")
public class ModeloTabla extends AbstractTableModel implements Memory.Observer {

	/* Modelo de la tabla de memoria compuesto por un TreeMap que simulará el comportamiento de la
	 * memoria de la CPU
	 * */
	
	private TreeMap<Integer,Integer> memoriaAux;
	private String[] columnNames = { "DIRECCIÓN", "VALOR" };
	
	public ModeloTabla() {
		memoriaAux = new TreeMap<Integer, Integer>();
	}
	
	// Metodos que devuelven el numero de filas y columnas de la tabla
	
	@Override
	public int getColumnCount() {
		// TODO Auto-generated method stub
		return columnNames.length;
	}

	@Override
	public int getRowCount() {
		// TODO Auto-generated method stub
		return memoriaAux.size();
	}

	// Metodo que devuelve un valor dado de la tabla a partir de dos argumentos
	@Override
	public Object getValueAt(int arg0, int arg1) {
		@SuppressWarnings("unchecked")
		Map.Entry<Integer, Integer>[] celdas = memoriaAux.entrySet().toArray(new Map.Entry[memoriaAux.size()]);
		
		if ( arg1 == 0)
		return celdas[arg0].getKey();
		else return celdas[arg0].getValue();
	}
	
	// Metodo que devuelve el nombre de un columna dado un índice
	public String getColumnName( int index ) {
		return columnNames[index];
		
	}
	
	public void inserta( int pos, int value) { // Inserta en la tabla una celda de memoria
		memoriaAux.put(pos, value);
	}
	

		
	public void imprimeMemoria() { // Dada una memoria vamos insertando las celdas de memoria en la tabla

		@SuppressWarnings("unchecked")
		Map.Entry<Integer, Integer>[] celdas = memoriaAux.entrySet().toArray(new Map.Entry[memoriaAux.size()]);
		
		for ( int i = 0; i < celdas.length; i++ )
			inserta( celdas[i].getKey(), celdas[i].getValue() );
		
		
		fireTableDataChanged(); // Finalmente se llama a la tabla para que sea repintada y se reflejen los cambios
		
	}
	
	public void resetTable() {
		memoriaAux.clear();
	}

	@Override
	public void onReset() {
		resetTable();

		SwingUtilities.invokeLater(
				new Runnable() {
				 		public void run() {
				 			imprimeMemoria();
				 		}
				}
		);
	}

	@Override
	public void onWrite(int pos, int val) {
		inserta(pos,val);
		
		SwingUtilities.invokeLater(
				new Runnable() {
				 		public void run() {
				 			imprimeMemoria();
				 		}
				}
		);
	}
	
	

}
